package com.kakarote.examine.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.kakarote.core.common.cache.CrmCacheKey;
import com.kakarote.core.entity.UserInfo;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.feign.examine.entity.ExamineDataSaveBO;
import com.kakarote.core.feign.examine.entity.ExamineFlowVO;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.BaseUtil;
import com.kakarote.core.utils.UserCacheUtil;
import com.kakarote.core.utils.UserUtil;
import com.kakarote.examine.constant.ExamineStatusEnum;
import com.kakarote.examine.constant.ExamineTypeEnum;
import com.kakarote.examine.entity.PO.*;
import com.kakarote.examine.mapper.ExamineFlowSuperiorMapper;
import com.kakarote.examine.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 审批流程主管审批记录表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-11-13
 */
@Service("superiorService")
public class ExamineFlowSuperiorServiceImpl extends BaseServiceImpl<ExamineFlowSuperiorMapper, ExamineFlowSuperior> implements IExamineFlowSuperiorService, ExamineTypeService {

    @Autowired
    private AdminService adminService;

    @Autowired
    private IExamineFlowFinalOptionalService examineFlowFinalOptionalService;

    @Autowired
    private IExamineFlowFinalService examineFlowFinalService;

    @Autowired
    private IExamineRecordLogService examineRecordLogService;

    @Autowired
    private IExamineService examineService;

    @Autowired
    private IExamineFlowService examineFlowService;

    @Autowired
    private IExamineRecordService examineRecordService;

    /**
     * 保存额外的审批流程data对象
     *
     * @param dataSaveBO data
     * @param flowId     审批流程ID
     */
    @Override
    public void saveExamineFlowData(ExamineDataSaveBO dataSaveBO, Long flowId, String batchId) {
        ExamineFlowSuperior flowSuperior = new ExamineFlowSuperior();
        flowSuperior.setParentLevel(dataSaveBO.getParentLevel());
        flowSuperior.setFlowId(flowId);
        flowSuperior.setType(dataSaveBO.getType());
        flowSuperior.setBatchId(batchId);
        save(flowSuperior);
    }

    /**
     * 通过batchId查询所有flow关联对象
     *
     * @param map     缓存对象
     * @param batchId batchId
     */
    @Override
    public void queryFlowListByBatchId(Map<String, Object> map, String batchId) {
        List<ExamineFlowSuperior> continuousSuperiors = lambdaQuery().eq(ExamineFlowSuperior::getBatchId, batchId).list();
        Map<Long, List<ExamineFlowSuperior>> collect = continuousSuperiors.stream().collect(Collectors.groupingBy(ExamineFlowSuperior::getFlowId));
        map.put(ExamineTypeEnum.SUPERIOR.getServerName(), collect);
    }

    /**
     * 查询详情页需要的审批详情
     *
     * @param examineFlow 当前审批流程
     * @param map         缓存的map
     * @return data
     */
    @Override
    @SuppressWarnings("unchecked")
    public ExamineFlowVO createFlowInfo(ExamineFlow examineFlow, Map<String, Object> map, List<UserInfo> userInfoList, Long ownerUserId) {
        UserInfo userInfo;
        if (ownerUserId != null) {
            userInfo = UserCacheUtil.getUserInfo(ownerUserId);
        } else {
            userInfo = UserCacheUtil.getUserInfo(UserUtil.getUserId());
        }
        ExamineFlowVO examineFlowVO = new ExamineFlowVO();
        Map<Long, List<ExamineFlowSuperior>> collect = (Map<Long, List<ExamineFlowSuperior>>) map.get(ExamineTypeEnum.SUPERIOR.getServerName());
        List<ExamineFlowSuperior> superiors = collect.get(examineFlow.getFlowId());
        if (superiors == null || superiors.size() == 0) {
            return null;
        }
        ExamineFlowSuperior continuousSuperior = superiors.get(0);
        List<SimpleUser> userList = new ArrayList<>();
        examineFlowVO.setExamineType(examineFlow.getExamineType());
        Integer examineErrorHandling = examineFlow.getExamineErrorHandling();
        examineFlowVO.setExamineErrorHandling(examineErrorHandling);
        examineFlowVO.setType(continuousSuperior.getType());
        List<Long> userIds = new ArrayList<>();
        if (userInfo.getParentId() != null && userInfo.getParentId() != 0) {
            List<Long> longList = queryUser(userInfoList, userInfo.getParentId());
            Long userId = null;
            //说明该员工并没有那么多上级
            if (continuousSuperior.getParentLevel() > longList.size()) {
                Integer type = continuousSuperior.getType();
                //当设置为找不到主官时，由上级主管代审批，才会由上级主管代审批
                if (type == 1) {
                    userId = longList.get(longList.size() - 1);
                }
            } else {
                userId = longList.get(continuousSuperior.getParentLevel() - 1);
            }
            //当用户不为空，加入用户，否则审批管理员审批该条数据
            if (userId != null) {
                userIds.add(userId);
            }
        }
        //对当前用户进行筛选，判断是否已经被禁用等操作
        List<Long> list = handleUserIdList(userIds);
        for (UserInfo info : userInfoList) {
            for (Long userId : list) {
                if (userId.equals(info.getUserId())) {
                    userList.add(toSimPleUser(info));
                    break;
                }
            }
        }
        examineFlowVO.setType(list.size() == 1 ? continuousSuperior.getType() : 3);
        examineFlowVO.setFlowId(examineFlow.getFlowId());
        examineFlowVO.setName(examineFlow.getName());
        examineFlowVO.setParentLevel(continuousSuperior.getParentLevel());
        examineFlowVO.setUserList(userList);
        return examineFlowVO;
    }

    private List<Long> queryUser(List<UserInfo> userInfoList, Long userId) {
        List<Long> idList = new ArrayList<>();
        //管理员没有上级
        if (userId == null || userId == 0 || userInfoList.isEmpty()) {
            idList.add(userId);
            return idList;
        }
        for (UserInfo userInfo : userInfoList) {
            if (userId.equals(userInfo.getUserId())) {
                idList.add(userId);
                if (userInfo.getParentId() == null || userInfo.getParentId() == 0) {
                    return idList;
                }
                idList.addAll(queryUser(userInfoList, userInfo.getParentId()));
            }
        }
        return idList;
    }

    /**
     * 处理当前节点
     *
     * @param examineFlow 当前处理节点
     * @param recordId    审核记录ID
     * @param data        特殊处理所需数据
     * @param examine     审核对象
     * @param init        是否初始化
     * @return data
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject disposeFlow(ExamineFlow examineFlow, Long recordId, Object data, Examine examine, boolean init) {
        ExamineFlowSuperior flowSuperior = lambdaQuery()
                .eq(ExamineFlowSuperior::getFlowId, examineFlow.getFlowId())
                .one();
        if (examine == null) {
            if (examineFlow.getExamineId().equals(0L)) {
                Long examineId = examineFlowService.lambdaQuery().eq(ExamineFlow::getBatchId, examineFlow.getBatchId()).ne(ExamineFlow::getExamineId, 0).select(ExamineFlow::getExamineId).last("limit 1").one().getExamineId();
                examineFlow.setExamineId(examineId);
            }

            examine = examineService.getById(examineFlow.getExamineId());
        }
        ExamineRecord examineRecord = examineRecordService.getById(recordId);
        Long createUserId = examineRecord.getCreateUserId();

        ExamineFlowFinal examineFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, examineFlow.getFlowId())
                .eq(ExamineFlowFinal::getRecordId, recordId).one();

        if (examineFlowFinal == null) {
            Integer maxSort = examineFlowFinalService.getMaxSort(recordId, examine.getExamineId());
            examineFlowFinal = new ExamineFlowFinal();
            examineFlowFinal.setName(examineFlow.getName());
            examineFlowFinal.setExamineType(examineFlow.getExamineType());
            examineFlowFinal.setFlowId(examineFlow.getFlowId());
            examineFlowFinal.setExamineErrorHandling(examineFlow.getExamineErrorHandling());
            examineFlowFinal.setCreateTime(new Date());
            examineFlowFinal.setCreateUserId(UserUtil.getUserId());
            examineFlowFinal.setExamineId(examine.getExamineId());
            examineFlowFinal.setRecordId(recordId);
            examineFlowFinal.setType(flowSuperior.getType());
            examineFlowFinal.setSort(maxSort + 1);
            examineFlowFinalService.save(examineFlowFinal);
        }


        UserInfo userInfo = UserCacheUtil.getUserInfo(createUserId);
        List<UserInfo> userInfoList = adminService.queryUserInfoList().getData();

        List<Long> userIds = new ArrayList<>();
        if (userInfo.getParentId() != null && userInfo.getParentId() != 0) {
            List<Long> longList = queryUser(userInfoList, userInfo.getParentId());
            Long userId = null;
            //说明该员工并没有那么多上级
            if (flowSuperior.getParentLevel() > longList.size()) {
                Integer type = flowSuperior.getType();
                //当设置为找不到主官时，由上级主管代审批，才会由上级主管代审批
                if (type == 1) {
                    userId = longList.get(longList.size() - 1);
                }
            } else {
                userId = longList.get(flowSuperior.getParentLevel() - 1);
            }
            //当用户不为空，加入用户，否则审批管理员审批该条数据
            if (userId != null) {
                userIds.add(userId);
            }
        }

        List<ExamineFlowFinalOptional> userList = examineFlowFinalOptionalService.lambdaQuery().eq(ExamineFlowFinalOptional::getRecordId, recordId)
                .eq(ExamineFlowFinalOptional::getFlowId, examineFlow.getFlowId()).list();
        if (userList == null || userList.size() == 0) {
            userList = castFlowOptionalUser(userIds, flowSuperior.getFlowId(), recordId, flowSuperior.getType());
            examineFlowFinalOptionalService.saveBatch(userList);
        }

        List<ExamineRecordLog> recordLogs = new LinkedList<>();

        String batchId = IdUtil.simpleUUID();
        LocalDateTime now = LocalDateTimeUtil.now();
        for (ExamineFlowFinalOptional examineFlowFinalUser : userList) {
            ExamineRecordLog examineRecordLog = new ExamineRecordLog();
            examineRecordLog.setLogId(BaseUtil.getNextId());
            examineRecordLog.setType(examineFlowFinal.getType());
            examineRecordLog.setCreateTime(now);
            examineRecordLog.setExamineTime(now);
            examineRecordLog.setUpdateTime(null);
            examineRecordLog.setCreateUserId(UserUtil.getUserId());
            examineRecordLog.setExamineId(examineFlowFinal.getExamineId());
            examineRecordLog.setExamineRoleId(0L);
            //   在这块判断审核人状态，是否有效等
            examineRecordLog.setExamineUserId(examineFlowFinalUser.getUserId());
            if (examineFlowFinal.getType() == 1) {
                if (userList.indexOf(examineFlowFinalUser) == 0) {
                    examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                } else {
                    examineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                }
            } else {
                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());

            }
            if (ObjectUtil.isNotNull(examineFlowFinalUser.getUserId())) {
                BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + examineFlowFinalUser.getUserId().toString());
            }
            examineRecordLog.setFlowId(examineFlowFinal.getFlowId());
            examineRecordLog.setRecordId(recordId);
            examineRecordLog.setSort(examineFlowFinalUser.getSort());
            examineRecordLog.setBatchId(batchId);
            recordLogs.add(examineRecordLog);
        }

        examineRecordLogService.saveBatch(recordLogs);
        return ExamineTypeService.super.disposeFlow(examineFlow, recordId, data, examine, init);
    }

}
